#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QTcpSocket>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 初始化TCPServer:使用对象树进行管理
    tcpserver = new QTcpServer(this);
    // 设置窗口标题
    this->setWindowTitle("服务器");
    // 通过信号槽定义处理收到连接后的处理函数
    connect(tcpserver, &QTcpServer::newConnection, this, &Widget::processConnection);
    // 监听并绑定端口号:这个操作得是初始化的最后一步，都是需要把如何处理连接，如何处理请求，都准备好之后，才能真正绑定端口并监听
    // 注意监听和绑定也可能是会失败的
    bool ret = tcpserver->listen(QHostAddress::Any, 8080);
    if(!ret)
    {
        QMessageBox::critical(this, "服务器出错", tcpserver->errorString());
        return;
    }
    // 此时就可以收取客户端的连接了
}

Widget::~Widget()
{
    delete ui;
}

void Widget::processConnection()
{
    // 收到客户端的连接请求之后，该怎么处理
    // 获取客户端的 socket
    QTcpSocket* socket = tcpserver->nextPendingConnection();
    // 设置一个日志表示连接成功
    QString log = "[" + socket->peerAddress().toString() + ":" + QString::number(socket->peerPort()) + "] 客户端上线！";
    ui->listWidget->addItem(log);
    // 接下来就可以接受客户端发来的数据了：通过信号槽来获取客户端是否发送了数据以及发送了什么数据
    connect(socket, &QTcpSocket::readyRead, this, [=](){
        // 获取客户端发送的数据
        QString requestData = socket->readAll();
        // 通过发送过来的数据构建响应
        const QString& responseData = process(requestData);
        // 发送至客户端
        socket->write(responseData.toUtf8());
        // 打印日志到列表框中，表示发送成功
        QString log = "[" + socket->peerAddress().toString() + ":" + QString::number(socket->peerPort()) + "]: "
                + "request:" + requestData + ", response: " + responseData;
        ui->listWidget->addItem(log);
    });
    // 通过信号槽，来处理客户端连接断开的情况
    connect(socket, &QTcpSocket::disconnected, this, [=](){
        // 打印日志到列表框中
        QString log = "[" + socket->peerAddress().toString() + ":" + QString::number(socket->peerPort()) + "] 客户端下线！";
        ui->listWidget->addItem(log);
        // 手动释放客户端的socket，直接使用delete是下策，用deleteLater更加合适
        // delete socket;
        socket->deleteLater();
    });
}

QString Widget::process(const QString &request)
{
    return request;
}

